core.define("view", ["$", "util"], function ($, util) {
    var cid = 0;

    var viewOptsMap = {
        elem : null,
        tagName : null,
        events : null,
        id : null
    };

    var View = function(opts) {
        if(!opts) opts = {};
        this.cid = "view" + (++cid);
        for(var key in opts) {
            if(key in viewOptsMap) {
                this[key] = opts[key];
            }
        }
        this._ensureElement();
        this.initialize.apply(this, arguments);
        this.delegateEvents();
    };

    $.extend(View.prototype, {
        tagName : "div",

        //to be overrided
        initialize : function() {},

        //to be overrided
        render : function() {
            return this;
        },

        setElement : function(elem, delegate) {
            if(this.$elem) this.undelegateEvents();
            this.$elem = elem instanceof $ ? elem : $(elem);
            this.elem = this.$elem[0];
            if(delegate !== false) this.delegateEvents();
            return this;
        },

        delegateEvents : function(events) {
            events = events || this.events;
            if(!events) return;
            this.undelegateEvents();
            for(var key in events) {
                var method = events[key];
                if(typeof method !== "function") method = this[method];
                if(!method) continue;
                method = $.proxy(method, this);
                var match = key.split(" "),
                    eventName = match[0],
                    selector = match[1];
                eventName += ".delegateEvents" + this.cid;
                if(!selector) {
                    this.$elem.on(eventName, method);
                } else {
                    this.$elem.delegate(selector, eventName, method);
                }
            }
            return this;
        },

        undelegateEvents : function() {
            this.$elem.off(".delegateEvents" + this.cid);
            return this;
        },

        $ : function(selector) {
            return this.$elem.find(selector);
        },

        destory : function() {
            this.$elem.remove();
            return this;
        },

        _ensureElement : function() {
            if (!this.elem) {
                var $elem = $('<' + this.tagName + '>');
                this.setElement($elem, false);
            } else {
                this.setElement(this.elem, false);
            }
        }
    });

    View.extend = util.extend;

    return View;
});